#ifndef _OCTNODE_H
#define _OCTNODE_H

#include "volume3D.h"


/*
octNode 
*/


//3D block pool
struct blockPoolElement
{
	volume3D *pVol;
	bool isUpdate;

}typedef;

//2D node pool
struct nodePoolElement
{
	unsigned int ID;
	unsigned int selfNodeClusterPointer[3];
	unsigned int childrenNodeClusterPointer[3];
	unsigned int childrenIndex;
	unsigned int blockPointer[3];
	float singleValue;
	unsigned char RGBA[4];
}typedef;


class octNode
{	
public:

	//octNode();
	octNode(int z, int y, int x, int blockSize,octNode* parent=0);
	octNode(int z, int y, int x, volume3D* vol, octNode* parent=0);
	octNode(int z, int y, int x, int blockSize, int rangMinZ,int rangMinY,int rangMinX,
		int rangMaxZ,int rangMaxY,int rangMaxX, int level, octNode* parent);
	~octNode();
	void setRange(int minZ, int minY, int minX, int maxZ, int maxY, int maxX);
	void getRange(int &minZ, int &minY, int &minX, int &maxZ, int &maxY, int &maxX);


	//children parents
	void addChild(int z, int y, int x, octNode* node);
	void removeChild(int z, int y, int x);

	octNode* getChild(int z, int y, int x); //x,y,z is coordinate of the chidren 
	octNode* getParent();
	int getPosX();
	int getPosY();
	int getPosZ();
	//TODO
	octNode* getRoot();


	bool isAllChildrenEmpty();
	bool isAllChildrenSameSingleColor(float similarFactor);
	int getVoxelByteSizeFromChildren();

	//level
	int getLevel();
	void setLevel(int level);
	bool isLeaf(); //if _block == 0
	bool isRoot(); //if no parents
	bool isSingleColor();
	bool isProcessed();
	void setProcessed();

	//volume
	void setVolume(volume3D* block);
	volume3D* getVolume();
	float getVolumeSingleValue();
	//cull volume: if it is homogenous convert to single color
	//recursive
	void cullVolumeByValue(float value);
	void cullToSingleColorNodeByValue(float value, float singleValueFactor);

	int getBlockNumInSubTree();
	int getNonLeafBlockNumInSubTree();
	int getNodeNumInSubTree();
	int getNonLeafNodeNumInSubTree();

	//recursive call
	void update();
	void updateNodeIndex(octNode*, int &index);
	void buildTree(int level);
	void buildDownSamplingTreeFromLeaf(volume3D *vol); //also loading leaf level here

	//with boundary
	void buildDownSamplingTreeWithBoundaryFromLeaf(volume3D *vol, float cullFactor, float singleColorFactor); 

	//TODO
	nodePoolElement nodeInfo;

private:
	void initNode();
	octNode* _children[2][2][2];
	octNode* _parent;
	volume3D* _vol;
	
	int _posX, _posY,_posZ;//position relation to siblings
	int _range[2][3];//position 0,0,0-1,1,1 range in virtual volume
	int _blockSize;

	int _level;
	bool _isLeaf;
	bool _isProcessed;

	//TODO consider this later
	bool _isSingleColor;
	unsigned char _colorVec[4];
	float _singleValue;

	int _blockNumInSubTree;
	int _nonLeafBlockNumInSubTree;
	int _nodeNumInSubTree;
	int _nonLeafNodeNumInSubTree;



};


#endif